prostore-react
Данный адаптер предоставляет набор полезных инструментов
для интеграции prostore
в React
.
Можно прокидывать сторы через контекст и
подписываться на сторы с помощью хуков,
а также автоматически выполнять запросы в RequestStore
.
Использование
Для примеров ниже будет использован простой стор,
считающий количество вызовов функции increment
:
import { BehaviorStore } from '@proscom/prostore';
const initialState = {
number: 0
};
export class IncStore extends BehaviorStore {
constructor() {
super(initialState);
}
increment() {
this.setState({
number: this.state.number + 1
});
}
}
import { IncStore } from './IncStore';
export const incStore = new IncStore();
useStore
Основной хук, который позволяет подписать компонент на
все изменения стора
import { useStore } from '@proscom/react';
import { incStore } from './incStore';
function MyComponent() {
const [state, store] = useStore(incStore);
const onClick = () => {
store.increment();
};
return <button onClick={onClick}>{state.number}</button>;
}
useStoreState
Иногда сам стор не нужен, а нужно только его состояние.
Тогда можно использовать этот хук, чтобы не делать лишнюю
деструктуризацию:
function MyComponent() {
const state = useStoreState(incStore);
return <div>{state.number}</div>;
}
ProstoreContext
Контекст позволяет прокидывать инстансы сторов в компоненты
по ключам. Таким образом реализуется принцип Dependency Injection
и снижается связанность компонентов и сторов.
export const STORE_TEST = 'STORE_TEST';
import ReactDOM from 'react-dom';
import { STORE_TEST } from './stores';
import { IncStore } from './IncStore';
import { App } from './App';
import { ProstoreContext } from '@proscom/prostore-react';
const testStore = new IncStore();
const stores = {
[STORE_TEST]: testStore
};
ReactDOM.render(
<ProstoreContext.Provider value={stores}>
<App />
</ProstoreContext.Provider>,
document.getElementById('root')
);
import { useStore } from '@proscom/react';
import { STORE_TEST } from './stores';
function App() {
const [state, store] = useStore(STORE_TEST);
const onClick = () => {
store.increment();
};
return <button onClick={onClick}>{state.number}</button>;
}
useContextStore
Иногда состояние стора в компоненте вообще не нужно,
а нужен только сам стор для вызова его методов.
При использовании сторов как глобальных переменных можно просто
вызывать их методы:
import { incStore } from './incStore';
function IncButton() {
return <button onClick={() => incStore.increment()}>Increment</button>;
}
При использовании контекста можно получить доступ к стору
с помощью хука useContextStore
. По сравнению с использованием
useStore
это избавит компонент от лишних перерендеров при изменении
состояния стора.
import { useContextStore } from '@proscom/react';
import { STORE_TEST } from './stores';
function IncButton() {
const incStore = useContextStore(STORE_TEST);
return <button onClick={() => incStore.increment()}>Increment</button>;
}
useRequestStore
При использовании RequestStore можно воспользоваться специальным
хуком useRequestStore
, чтобы автоматически выполнять запрос
при изменении его переменных, а также отслеживать состояние запроса
(идет загрузка, ошибка, готов результат).
import { AxiosQueryStore } from '@proscom/prostore-axios';
import { useRequestStore } from '@proscom/prostore-react';
const store = new AxiosQueryStore();
function MyComponent() {
const variables = {
params: {
page: 1
}
};
const options = undefined;
const query = useRequestStore(store, variables, options);
const { check, state, load } = query;
if (check.spinner) {
return <Spinner />;
} else if (check.error) {
return <ErrorMessage error={state.error} />;
}
return <Info data={state.data} refresh={load} />;
}
При каждом рендере useRequestStore
глубоко сравнивает
предыдущие переменные с новыми, и если есть отличия, то
вызывает выполнение запроса с новыми переменными.
Под глубоким сравнением понимается
lodash.isEqual
.
options
передаются вторым аргументом в store.loadData
в неизменном виде. При изменении options
запрос не будет повторен.
useRequestStore
можно также использовать с контекстом:
import { STORE_TEST } from './stores';
import { useRequestStore } from '@proscom/prostore-react';
function MyComponent() {
const variables = {};
const query = useRequestStore(STORE_TEST, variables);
}